﻿using System.ComponentModel;
using System.Windows;
using System.Windows.Markup;

namespace Geometry
{
    public sealed class CompassCircle: GObjectBase, IGCircle 
    {
        public CompassCircle()
        {
            UpdateBoundingBox();
        }

        public CompassCircle(IGPoint _point1, IGPoint _point2)
        {
            this.CentrePoint = _point1;
            this.PerimeterPoint = _point2;
            UpdateBoundingBox();
        }

        protected override void ReleaseDependencies()
        {
            this.CentrePoint = null;
            this.PerimeterPoint = null;
        }

        protected override void UpdateBoundingBox()
        {
            base.BoundingBox = new Rect(Centre - new Vector(Radius, Radius), Centre + new Vector(Radius, Radius));
        }

        private IGPoint m_CentrePoint;
        [ValueSerializer(typeof(ElementReferenceSerializer))]
        [TypeConverter(typeof(PlaceHolderTypeConverter))]
        public IGPoint CentrePoint
        {
            get
            {
                return m_CentrePoint;
            }
            set
            {
                if (m_CentrePoint == value) return;

                if (m_CentrePoint != null) m_CentrePoint.PropertyChanged -= _related_PropertyChanged;
                m_CentrePoint = value;
                if (m_CentrePoint != null) m_CentrePoint.PropertyChanged += _related_PropertyChanged;

                RaisePropertyChanged("CentrePoint");
                UpdateCalculations();
            }
        }

        private IGPoint m_PerimeterPoint;
        [ValueSerializer(typeof(ElementReferenceSerializer))]
        [TypeConverter(typeof(PlaceHolderTypeConverter))]
        public IGPoint PerimeterPoint
        {
            get
            {
                return m_PerimeterPoint;
            }
            set
            {
                if (m_PerimeterPoint == value) return;

                if (m_PerimeterPoint != null) m_PerimeterPoint.PropertyChanged -= _related_PropertyChanged;
                m_PerimeterPoint = value;
                if (m_PerimeterPoint != null) m_PerimeterPoint.PropertyChanged += _related_PropertyChanged;

                RaisePropertyChanged("PerimeterPoint");
                UpdateCalculations();
            }
        }

        private void _related_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName != "Position") return;

            UpdateCalculations();
        }

        private void UpdateCalculations()
        {
            if (m_CentrePoint.IsNullOrPlaceHolder()) return;
            if (m_PerimeterPoint.IsNullOrPlaceHolder()) return;
            this.Centre = m_CentrePoint.Position;
            this.Radius = (m_PerimeterPoint.Position - m_CentrePoint.Position).Length;
        }

        #region IGCircle Members

        private double m_Radius;
        public double Radius
        {
            get { return m_Radius; }
            private set
            {
                if (value.Equals(m_Radius)) return;
                m_Radius = value;
                UpdateBoundingBox();
                RaisePropertyChanged("Radius");
            }
        }

        private Point m_Centre;
        public Point Centre
        {
            get { return m_Centre; }
            private set
            {
                if (value.Equals(m_Centre)) return;
                m_Centre = value;
                UpdateBoundingBox();
                RaisePropertyChanged("Centre");
            }
        }

        #endregion
    }
}
